package com.love.marriage.userBalanceInfo.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;
import com.love.marriage.cloud.service.AliyunDysmsService;
import com.love.marriage.cloud.service.WechatService;
import com.love.marriage.common.enums.DefaultAmountTypeEnum;
import com.love.marriage.common.enums.ResultEnum;
import com.love.marriage.common.enums.TransactionSource;
import com.love.marriage.common.enums.TransactionType;
import com.love.marriage.common.exceptions.SystemException;
import com.love.marriage.defaultAmountConfig.service.DefaultAmountConfigService;
import com.love.marriage.defaultAmountConfig.vo.DefaultAmountConfigVo;
import com.love.marriage.matchmakerInfo.service.MatchmakerInfoService;
import com.love.marriage.matchmakerInfo.vo.MatchmakerInfoVo;
import com.love.marriage.offlineServiceProvider.service.OfflineServiceProviderService;
import com.love.marriage.offlineServiceProvider.vo.OfflineServiceProviderVo;
import com.love.marriage.orderInfo.service.OrderInfoService;
import com.love.marriage.orderInfo.vo.OrderInfoVo;
import com.love.marriage.partnerCategoryConfig.mapper.PartnerCategoryConfigMapper;
import com.love.marriage.partnerCategoryConfig.vo.PartnerCategoryConfigVo;
import com.love.marriage.rechargePackageInfo.service.RechargePackageInfoService;
import com.love.marriage.rechargePackageInfo.vo.RechargePackageInfoVo;
import com.love.marriage.regionInfo.service.RegionInfoService;
import com.love.marriage.userBalanceInfo.entity.UserBalanceInfo;
import com.love.marriage.userBalanceInfo.mapper.UserBalanceInfoMapper;
import com.love.marriage.userBalanceInfo.service.UserBalanceInfoService;
import com.love.marriage.userBalanceInfo.vo.UserBalanceInfoAddVo;
import com.love.marriage.userBalanceInfo.vo.UserBalanceInfoVo;
import com.love.marriage.userCallRetrieval.service.UserCallRetrievalService;
import com.love.marriage.userChatInfo.entity.UserChatInfo;
import com.love.marriage.userChatInfo.mapper.UserChatInfoMapper;
import com.love.marriage.userChatInfo.vo.UserChatInfoVo;
import com.love.marriage.userInfo.service.UserInfoService;
import com.love.marriage.userInfo.vo.UserInfoVo;
import com.love.marriage.userMembershipInfo.vo.UserReduceMoneyVo;
import com.love.marriage.userRechargeRecordInfo.service.UserRechargeRecordInfoService;
import com.love.marriage.userRechargeRecordInfo.vo.UserRechargeRecordInfoVo;
import com.love.marriage.userTransactionInfo.service.UserTransactionInfoService;
import com.love.marriage.userTransactionInfo.vo.UserTransactionInfoVo;
import com.love.marriage.utils.OrderCodeUtils;
import com.love.marriage.utils.StringUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

/**
 * <p>
 * description:  用户余额表服务实现类
 * author:       mybatisPlus
 * createDate:   2024-10-17 21:19:44
 * version:      1.0.0
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class UserBalanceInfoServiceImp extends ServiceImpl<UserBalanceInfoMapper, UserBalanceInfo> implements UserBalanceInfoService {

    private final UserBalanceInfoMapper userBalanceInfoMapper;

    private final RechargePackageInfoService rechargePackageInfoService;

    private final UserRechargeRecordInfoService userRechargeRecordInfoService;

    private final UserTransactionInfoService userTransactionInfoService;

    private final DefaultAmountConfigService defaultAmountConfigService;

    private final UserChatInfoMapper userChatInfoMapper;

    private final WechatService wechatService;

    private final OrderInfoService orderInfoService;

    private final UserCallRetrievalService userCallRetrievalService;

    private final PartnerCategoryConfigMapper partnerCategoryConfigMapper;

    private final AliyunDysmsService aliyunDysmsService;

    private final RegionInfoService regionInfoService;

    private final OfflineServiceProviderService offlineServiceProviderService;

    private final MatchmakerInfoService matchmakerInfoService;

    private final UserInfoService userInfoService;

    @Override
    public Page<UserBalanceInfoVo> getPage(Long pageNum, Long pageSize, UserBalanceInfoVo userBalanceInfoVo) {
        Page<UserBalanceInfoVo> page = new Page<>(pageNum == null ? 1 : pageNum, pageSize == null ? 10 : pageSize);
        return userBalanceInfoMapper.getPage(page, userBalanceInfoVo);
    }

    @Override
    public UserBalanceInfoVo queryUserBalanceInfo(Long id) {
        return userBalanceInfoMapper.queryUserBalanceInfo(id);
    }

    @Override
    public UserBalanceInfoVo queryUserBalanceInfoByUserId(Long userId) {
        return userBalanceInfoMapper.queryUserBalanceInfoByUserId(userId);
    }

    @Override
    public UserBalanceInfoVo addUserBalanceInfo(UserBalanceInfoVo userBalanceInfoVo) {
        UserBalanceInfo userBalanceInfo = new UserBalanceInfo();
        BeanUtils.copyProperties(userBalanceInfoVo, userBalanceInfo);
        userBalanceInfoMapper.insert(userBalanceInfo);
        UserBalanceInfoVo res = new UserBalanceInfoVo();
        BeanUtils.copyProperties(userBalanceInfo, res);
        return res;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserBalanceInfoVo addAmountBack(OrderInfoVo orderInfoVo) throws Exception {
        // 如果充值包id不为空，则查询充值包记录
        // 支付金额
        BigDecimal payAmount;
        // 充值金额
        BigDecimal addAmount;
        // 赠送金额
        BigDecimal bonusAmount = null;
        if (orderInfoVo.getBusinessId() != null) {
            RechargePackageInfoVo rechargePackageInfoVo = rechargePackageInfoService.queryRechargePackageInfo(orderInfoVo.getBusinessId());
            payAmount = rechargePackageInfoVo.getAmount();
            addAmount = rechargePackageInfoVo.getBonusAmount().add(rechargePackageInfoVo.getAmount());
            bonusAmount = rechargePackageInfoVo.getBonusAmount();
        } else {
            payAmount = orderInfoVo.getTotalAmount();
            addAmount = orderInfoVo.getTotalAmount();
        }
        // 添加充值记录
        UserRechargeRecordInfoVo userRechargeRecordInfoVo = new UserRechargeRecordInfoVo();
        userRechargeRecordInfoVo.setUserId(orderInfoVo.getUserId());
        userRechargeRecordInfoVo.setAmount(payAmount);
        userRechargeRecordInfoVo.setBonusAmount(bonusAmount);
        userRechargeRecordInfoService.addUserRechargeRecordInfo(userRechargeRecordInfoVo);
        // 更新用户余额
        LambdaQueryWrapper<UserBalanceInfo> query = Wrappers.<UserBalanceInfo>lambdaQuery().eq(UserBalanceInfo::getUserId, orderInfoVo.getUserId());
        UserBalanceInfo dbBalanceVo = this.getOne(query);
        if (dbBalanceVo == null) {
            dbBalanceVo = new UserBalanceInfo();
            dbBalanceVo.setUserId(orderInfoVo.getUserId());
            dbBalanceVo.setBalance(addAmount);
            userBalanceInfoMapper.insert(dbBalanceVo);
        } else {
            dbBalanceVo.setBalance(dbBalanceVo.getBalance().add(addAmount));
            userBalanceInfoMapper.updateById(dbBalanceVo);
        }
        UserBalanceInfoVo res = new UserBalanceInfoVo();
        BeanUtils.copyProperties(dbBalanceVo, res);
        return res;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserBalanceInfoVo reduceAmount(UserBalanceInfoAddVo userBalanceInfoAddVo, Long relationId,
                                          String transactionType, String message) {
        if (userBalanceInfoAddVo.getAmount() == null) {
            throw new SystemException(ResultEnum.PARAM_ERROR);
        }
//        // 如果金额大于0则开始回佣
//        if (userBalanceInfoAddVo.getAmount().compareTo(BigDecimal.ZERO) > 0) {
//            // 获取乐缘币获取比例
//            DefaultAmountConfigVo rateVo = defaultAmountConfigService.queryDefaultAmountConfigByCode("default_ly_rate");
//            commissionCommonService.addTwoLevelCommission(userBalanceInfoAddVo.getUserId(), userBalanceInfoAddVo.getAmount().multiply(rateVo.getAmount()));
//        }
        // 判断余额是否充足
        UserBalanceInfoVo userBalanceInfoVo = queryUserBalanceInfoByUserId(userBalanceInfoAddVo.getUserId());
        if (userBalanceInfoVo == null || userBalanceInfoVo.getBalance().compareTo(userBalanceInfoAddVo.getAmount()) < 0) {
            throw new SystemException(ResultEnum.USER_NO_ENOUGH_BALANCE);
        }
        // TODO: 2024/10/17 打赏时官方账号需要添加金钱吗
        // 添加消费记录
        UserTransactionInfoVo userTransactionInfoVo = new UserTransactionInfoVo();
        userTransactionInfoVo.setUserId(userBalanceInfoAddVo.getUserId());
        userTransactionInfoVo.setTransactionAmount(userBalanceInfoAddVo.getAmount());
        userTransactionInfoVo.setTransactionTime(LocalDateTime.now());
        userTransactionInfoVo.setTransactionSource(TransactionSource.BALANCE.getCode());
        userTransactionInfoVo.setTransactionType(transactionType == null ? TransactionType.REDUCE_RECHARGE.getCode() : transactionType);
        userTransactionInfoVo.setRelatedBusinessId(relationId);
        userTransactionInfoVo.setDescription(message);
        userTransactionInfoService.addUserTransactionInfo(userTransactionInfoVo);
        UserBalanceInfo dbBalanceVo = changeBalance(userBalanceInfoAddVo.getUserId(), userBalanceInfoAddVo.getAmount().negate());
        UserBalanceInfoVo res = new UserBalanceInfoVo();
        BeanUtils.copyProperties(dbBalanceVo, res);
        return res;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public WxPayUnifiedOrderV3Result.JsapiResult reduceMoney(UserReduceMoneyVo userReduceMoneyVo) throws Exception {
        // 保存红娘信息时，需要校验用户是否保存了用户档案信息
        if ("matchmaker_save".equals(userReduceMoneyVo.getType())) {
            // 查询是否维护用户档案信息
//            UserProfileInfoVo dbProfile = userProfileInfoMapper.queryUserProfileInfoByUserId(userReduceMoneyVo.getUserId());
//            if (dbProfile != null && StringUtils.isNotBlank(dbProfile.getNickname())) {
//                throw new Exception("用户档案已维护，不能添加红娘信息");
//            }
        }
        if ("partner".equals(userReduceMoneyVo.getType())) {
            OfflineServiceProviderVo offlineServiceProviderVo = JSONObject.parseObject(userReduceMoneyVo.getRelatedBusinessInfo(), OfflineServiceProviderVo.class);
            if (StringUtils.isBlank(offlineServiceProviderVo.getPartnerType())) {
                throw new SystemException("1800002", "请输入正确的合作伙伴");
            }
            OfflineServiceProviderVo dbInfo = offlineServiceProviderService.queryOfflineServiceProviderByUserId(offlineServiceProviderVo.getUserId(), offlineServiceProviderVo.getType());
            // 异步发送短信通知
            sendSmsNotificationAsync(offlineServiceProviderVo);
            // 只有没保存过的，或者审核没通过的数据才保存数据
            if (dbInfo == null ||
                    dbInfo.getStatus() == 1 ||
                    (dbInfo.getStatus() == 2 && (dbInfo.getEndTime() == null || LocalDateTime.now().isAfter(dbInfo.getEndTime())))) {
                offlineServiceProviderVo.setStatus(1);
                offlineServiceProviderService.addInfo(offlineServiceProviderVo);
            }
        } else if ("matchmaker_save".equals(userReduceMoneyVo.getType())) {
            MatchmakerInfoVo matchmakerInfoVo = JSONObject.parseObject(userReduceMoneyVo.getRelatedBusinessInfo(), MatchmakerInfoVo.class);
            MatchmakerInfoVo dbInfo = matchmakerInfoService.queryNewMatchmakerByUserId(matchmakerInfoVo.getUserId());
            // 只有没保存过的，或者审核没通过的数据才保存数据
            if (dbInfo == null || dbInfo.getStatus() == null || dbInfo.getStatus() == 1) {
                matchmakerInfoVo.setStatus(1);
                matchmakerInfoService.addInfo(matchmakerInfoVo);
            }
        }
        if (userReduceMoneyVo.getAmount() != null && userReduceMoneyVo.getAmount().compareTo(BigDecimal.ZERO) < 0) {
            throw new Exception("金额错误");
        }
        // 获取订单金额
        BigDecimal payMoney;
        if (userReduceMoneyVo.getAmount() == null) {
            if ("partner".equals(userReduceMoneyVo.getType())) {
                OfflineServiceProviderVo offlineServiceProviderVo = JSONObject.parseObject(userReduceMoneyVo.getRelatedBusinessInfo(), OfflineServiceProviderVo.class);
                if (StringUtils.isBlank(offlineServiceProviderVo.getPartnerType())) {
                    throw new SystemException("1800002", "请输入正确的合作伙伴");
                }
                PartnerCategoryConfigVo query = new PartnerCategoryConfigVo();
                query.setCategoryCode(offlineServiceProviderVo.getPartnerType());
                PartnerCategoryConfigVo dbInfo = partnerCategoryConfigMapper.queryPartnerCategoryConfigInfo(query);
                if (dbInfo == null) {
                    throw new SystemException("1800001", "请输入正确的合作伙伴类型");
                }
                payMoney = dbInfo.getPrice();
            } else if ("create_dating_top".equals(userReduceMoneyVo.getType())) {
                DefaultAmountConfigVo db1 = defaultAmountConfigService.queryDefaultAmountConfigByCode("create_dating");
                DefaultAmountConfigVo db2 = defaultAmountConfigService.queryDefaultAmountConfigByCode("top_dating");
                userReduceMoneyVo.setType("create_dating");
                payMoney = db1.getAmount().add(db2.getAmount());
            } else {
                DefaultAmountConfigVo defaultAmountConfigVo = defaultAmountConfigService.queryDefaultAmountConfigByCode(userReduceMoneyVo.getType());
                if (defaultAmountConfigVo == null) {
                    throw new Exception("支付类型不存在");
                }
                payMoney = defaultAmountConfigVo.getAmount();
            }
        } else {
            payMoney = userReduceMoneyVo.getAmount();
            if ("create_dating_top".equals(userReduceMoneyVo.getType())) {
                userReduceMoneyVo.setType("create_dating");
            }
        }
        // 查询会员配置信息
        OrderInfoVo orderInfoVo = new OrderInfoVo();
        orderInfoVo.setUserId(userReduceMoneyVo.getUserId());
        orderInfoVo.setOrderNumber(OrderCodeUtils.generatorOrderNumber(getTypeInfo(userReduceMoneyVo.getType())));
        orderInfoVo.setTotalAmount(payMoney);
        orderInfoVo.setStatus("PENDING");
        orderInfoVo.setPaymentMethod("WECHAT_APP");
        orderInfoVo.setPaymentTime(LocalDateTime.now());
        orderInfoVo.setOrderDescription(getTypeMessageInfo(userReduceMoneyVo.getType()));
        orderInfoVo.setBusinessId(userReduceMoneyVo.getRelatedBusinessId());
        orderInfoVo.setBusinessInfo(userReduceMoneyVo.getRelatedBusinessInfo());
        orderInfoVo.setType(userReduceMoneyVo.getType());
        orderInfoVo.setSource(userReduceMoneyVo.getSource());
        OrderInfoVo dbOrder = orderInfoService.addOrderInfo(orderInfoVo);
        if ("end".equals(userReduceMoneyVo.getSource())) {
            return null;
        }
        return wechatService.unifiedOrder(userReduceMoneyVo.getUserId(), payMoney.multiply(new BigDecimal("100")).intValue(),
                userReduceMoneyVo.getType(), dbOrder.getOrderNumber(), dbOrder.getOrderDescription());
    }

    private UserBalanceInfo changeBalance(Long userId, BigDecimal amount) {
        // 更新用户余额
        LambdaQueryWrapper<UserBalanceInfo> query = Wrappers.<UserBalanceInfo>lambdaQuery().eq(UserBalanceInfo::getUserId, userId);
        UserBalanceInfo dbBalance = this.getOne(query);
        if (dbBalance == null) {
            dbBalance = new UserBalanceInfo();
            dbBalance.setUserId(userId);
            dbBalance.setBalance(amount);
            userBalanceInfoMapper.insert(dbBalance);
        } else {
            dbBalance.setBalance(dbBalance.getBalance().add(amount));
            userBalanceInfoMapper.updateById(dbBalance);
        }
        return dbBalance;
    }

    @Override
    public UserBalanceInfoVo updateUserBalanceInfo(UserBalanceInfoVo userBalanceInfoVo) {
        UserBalanceInfo userBalanceInfo = new UserBalanceInfo();
        BeanUtils.copyProperties(userBalanceInfoVo, userBalanceInfo);
        userBalanceInfoMapper.updateById(userBalanceInfo);
        return userBalanceInfoVo;
    }

    @Override
    public Boolean deleteUserBalanceInfo(String ids) {
        if (StringUtils.isEmpty(ids)) {
            return true;
        }
        List<String> idArr = Arrays.asList(ids.split(","));
        userBalanceInfoMapper.deleteBatchIds(idArr);
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean reduceBalanceByType(Long userId, String type) throws Exception {
        switch (type) {
            case "getPhone":
                // 判断是否有电话余额
                UserChatInfoVo userChatInfoVo = userChatInfoMapper.queryUserChatInfoByUserId(userId, DefaultAmountTypeEnum.GET_PHONE_NUM.getCode());
                // 如果会员默认提供的查看电话数量不为空且大于0，则直接扣减，否则扣减余额
                if (userChatInfoVo != null && userChatInfoVo.getChatCount() > 0) {
                    UserChatInfo userChatInfo = new UserChatInfo();
                    userChatInfo.setId(userChatInfoVo.getId());
                    userChatInfo.setChatCount(userChatInfoVo.getChatCount() - 1);
                    userChatInfoMapper.updateById(userChatInfo);
                    return true;
                }
                break;
            case "chat":
                // TODO: 2024/11/20 判断是否有聊天余额
            case "call":
                // TODO: 2024/11/20 判断是否有通话余额
        }

        // 判断余额是否充足
        UserBalanceInfoVo userBalanceInfoVo = queryUserBalanceInfoByUserId(userId);
        DefaultAmountConfigVo defaultAmountConfigVo = defaultAmountConfigService.queryDefaultAmountConfigByCode(type);
        if (defaultAmountConfigVo == null || defaultAmountConfigVo.getAmount() == null) {
            throw new Exception("请联系管理员配置类型及金额");
        }
        if (userBalanceInfoVo == null || userBalanceInfoVo.getBalance().compareTo(defaultAmountConfigVo.getAmount()) < 0) {
            throw new SystemException(ResultEnum.USER_NO_ENOUGH_BALANCE);
        }
        // 扣减余额
        UserBalanceInfoAddVo userBalanceInfoAddVo = new UserBalanceInfoAddVo();
        userBalanceInfoAddVo.setUserId(userId);
        userBalanceInfoAddVo.setAmount(defaultAmountConfigVo.getAmount());
        reduceAmount(userBalanceInfoAddVo, null, type, null);
        // 如果类型是获取手机号，则跟新获取查看手机次数
        if (type.contains("getPhone")) {
            userCallRetrievalService.addUserCallRetrievalCount(userBalanceInfoAddVo.getUserId());
        }
        return true;
    }

    private String getTypeInfo(String type) {
        switch (type) {
            case "getPhone1":
            case "getPhone2":
            case "getPhone3":
            case "getPhone":
            case "getPhone0":
                return "GP";
            case "payBalance":
                return "CZ";
            case "create_dating":
                return "CD";
            case "join_dating":
                return "JD";
            case "join_event":
                return "JE";
            case "chat":
                return "LT";
            case "call":
                return "TH";
            case "matchmaker_save":
                return "HN";
            case "partner":
                return "PN";
        }
        return "";
    }

    private String getTypeMessageInfo(String type) {
        switch (type) {
            case "getPhone":
            case "getPhone1":
            case "getPhone2":
            case "getPhone3":
            case "getPhone0":
                return "获取电话号码";
            case "payBalance":
                return "充值";
            case "create_dating":
                return "创建约会";
            case "join_dating":
                return "参加约会";
            case "join_event":
                return "参加活动";
            case "chat":
                return "聊天";
            case "matchmaker_save":
                return "保存红娘信息";
            case "partner":
                return "合伙人信息";
        }
        return "";
    }

    /**
     * 异步发送短信通知
     * 
     * @param offlineServiceProviderVo 线下服务商信息
     */
    @Async("taskExecutor")
    public void sendSmsNotificationAsync(OfflineServiceProviderVo offlineServiceProviderVo) {
        try {
            // 获取用户编码
            UserInfoVo userInfo = userInfoService.queryUserInfo(offlineServiceProviderVo.getUserId());
            String userCode = userInfo != null ? userInfo.getCode() : null;
            
            // 获取合伙人类型名称
            String partnerTypeName = null;
            if (StringUtils.isNotBlank(offlineServiceProviderVo.getPartnerType())) {
                PartnerCategoryConfigVo partnerQuery = new PartnerCategoryConfigVo();
                partnerQuery.setCategoryCode(offlineServiceProviderVo.getPartnerType());
                PartnerCategoryConfigVo partnerConfig = partnerCategoryConfigMapper.queryPartnerCategoryConfigInfo(partnerQuery);
                partnerTypeName = partnerConfig != null ? partnerConfig.getCategoryName() : null;
            }
            
            // 发送短信通知
            aliyunDysmsService.sendNoticeSms(null, offlineServiceProviderVo.getName(), userCode, partnerTypeName);
            
            log.info("异步发送短信成功 - 用户ID: {}, 用户编码: {}, 合伙人类型: {}", 
                    offlineServiceProviderVo.getUserId(), userCode, partnerTypeName);
                    
        } catch (Exception e) {
            log.error("异步发送短信失败 - 用户ID: {}, 错误信息: {}", 
                    offlineServiceProviderVo.getUserId(), e.getMessage(), e);
        }
    }
}
